﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace MyGUI
{
    public class TreeNode<T> : IList<TreeNode<T>>
    {
        public T Value { get; set; }
        public int Layer { get; private set; }
        public TreeNode<T> parent { get; private set; }

        List<TreeNode<T>> childs = new List<TreeNode<T>>();

        public int Count { get { return childs.Count; } }

        public bool IsReadOnly { get { return false; } }

        public TreeNode<T> this[int index] { get { return childs[index]; } set { childs[index] = value; } }

        public TreeNode()
        {
        }
        public TreeNode(T value)
        {
            this.Value = value;
        }

        public IEnumerator GetEnumerator()
        {
            return new Enumerator(childs);
        }

        public int IndexOf(TreeNode<T> item)
        {
            return childs.IndexOf(item);
        }

        public void Insert(int index, TreeNode<T> item)
        {
            item.parent = this;
            item.Layer = this.Layer + 1;
            childs.Insert(index, item);
        }

        public void RemoveAt(int index)
        {
            if (index >= childs.Count || index < 0)
            {
                throw new IndexOutOfRangeException();
            }
            childs[index].parent = null;
            childs[index].Layer = 0;
            childs.RemoveAt(index);
        }

        public void Add(TreeNode<T> item)
        {
            item.parent = this;
            item.Layer = this.Layer + 1;
            childs.Add(item);
        }

        public void Clear()
        {
            foreach (var item in childs)
            {
                item.parent = null;
                item.Layer = 0;
            }
            childs.Clear();
        }

        public bool Contains(TreeNode<T> item)
        {
            return childs.Contains(item);
        }

        public void CopyTo(TreeNode<T>[] array, int arrayIndex)
        {
            childs.CopyTo(array, arrayIndex);
        }

        public bool Remove(TreeNode<T> item)
        {
            var result = childs.Remove(item);
            if (result)
            {
                item.parent = null;
                item.Layer = 0;
            }
            return result;
        }

        public override string ToString()
        {
            if (Value == null)
                return string.Format("value is null");
            return Value.ToString();
        }

        IEnumerator<TreeNode<T>> IEnumerable<TreeNode<T>>.GetEnumerator()
        {
            return new Enumerator(childs);
        }


        struct Enumerator : IEnumerator<TreeNode<T>>
        {
            int index;
            List<TreeNode<T>> childs;
            public TreeNode<T> Current
            {
                get
                {
                    if (index >= 0 && index < childs.Count)
                    {
                        return childs[index];
                    }
                    throw new IndexOutOfRangeException();
                }
            }

            object IEnumerator.Current
            {
                get
                {
                    if (index >= 0 && index < childs.Count)
                    {
                        return childs[index];
                    }
                    throw new IndexOutOfRangeException();

                }
            }

            public Enumerator(List<TreeNode<T>> childs)
            {
                this.childs = childs;
                index = -1;
            }

            public void Dispose()
            {
                childs = null;
            }

            public bool MoveNext()
            {
                index++;
                return index < childs.Count;
            }

            public void Reset()
            {
                index = -1;
            }
        }
    }
}